// 《围棋》作者版权所有。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// go:generate go run-mod=mod mknode。go 

package ir

import (
	"cmd/compile/internal/types"
	"cmd/internal/src"
	"fmt"
	"go/constant"
)

// 迷你节点是一个最小的节点实现，
// 意味着作为更大节点实现的第一个字段嵌入，
// 成本为8字节。
// 
// 迷你节点本身不是有效节点：嵌入结构
// 必须至少提供：
// 
// func（n*MyNode）String（）String{return fmt.Sprint（n）}
// func（n*MyNode）rawCopy（）节点{c:=*n；return c:&c}
// func（n*MyNode）格式（s*runt.State，动词{（n，s，动词）}
// 
// 嵌入结构也应该在其构造函数中填写n.op，
// 要在调用无效方法时获得更有用的紧急消息，
// 而不是实现op本身。
// 
type miniNode struct {
	pos  src.XPos // uint32 
	op   Op       // uint8 
	bits bitset8
	esc  uint16
}

// posOr返回pos（如果已知），否则n.pos.
// 。
func (n *miniNode) posOr(pos src.XPos) src.XPos {
	if pos.IsKnown() {
		return pos
	}
	return n.pos
}

// op可以读，但不能写。
// 如果需要，嵌入实现可以提供SetOp。
// （恐慌的SetOp与下面的其他恐慌一起出现。）
func (n *miniNode) Op() Op            { return n.op }
func (n *miniNode) Pos() src.XPos     { return n.pos }
func (n *miniNode) SetPos(x src.XPos) { n.pos = x }
func (n *miniNode) Esc() uint16       { return n.esc }
func (n *miniNode) SetEsc(x uint16)   { n.esc = x }

const (
	miniWalkdefShift   = 0 // TODO（mdempsky）：转到Name。旗帜。
	miniTypecheckShift = 2
	miniDiag           = 1 << 4
	miniWalked         = 1 << 5 // 防止/捕获重新行走
)

func (n *miniNode) Typecheck() uint8 { return n.bits.get2(miniTypecheckShift) }
func (n *miniNode) SetTypecheck(x uint8) {
	if x > 2 {
		panic(fmt.Sprintf("cannot SetTypecheck %d", x))
	}
	n.bits.set2(miniTypecheckShift, x)
}

func (n *miniNode) Diag() bool     { return n.bits&miniDiag != 0 }
func (n *miniNode) SetDiag(x bool) { n.bits.set(miniDiag, x) }

func (n *miniNode) Walked() bool     { return n.bits&miniWalked != 0 }
func (n *miniNode) SetWalked(x bool) { n.bits.set(miniWalked, x) }

// 空的、不变的图形结构。

func (n *miniNode) Init() Nodes { return Nodes{} }

// 其他功能不可用。

func (n *miniNode) no(name string) string { return "cannot " + name + " on " + n.op.String() }

func (n *miniNode) Type() *types.Type       { return nil }
func (n *miniNode) SetType(*types.Type)     { panic(n.no("SetType")) }
func (n *miniNode) Name() *Name             { return nil }
func (n *miniNode) Sym() *types.Sym         { return nil }
func (n *miniNode) Val() constant.Value     { panic(n.no("Val")) }
func (n *miniNode) SetVal(v constant.Value) { panic(n.no("SetVal")) }
func (n *miniNode) NonNil() bool            { return false }
func (n *miniNode) MarkNonNil()             { panic(n.no("MarkNonNil")) }
